#pragma once
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <string.h>
#include <array>
#include <cassert>
#include <cstdint>
#include <expected>
#include <span>
#include <sstream>
#include <string>
#include <string_view>
namespace fastrpc::rpc::util {

// 读取 4 字节的 uint32_t
// static inline uint32_t read_u32(std::span<const char> bytes) {
//     if (bytes.size() < 4) {
//         throw std::out_of_range("Not enough data to read uint32_t");
//     }
//     uint32_t value = 0;
//     value |= static_cast<uint32_t>(bytes[0]) << 24;
//     value |= static_cast<uint32_t>(bytes[1]) << 16;
//     value |= static_cast<uint32_t>(bytes[2]) << 8;
//     value |= static_cast<uint32_t>(bytes[3]);
//     return value;
// }

std::string getEn0IP() {
    struct ifaddrs *ifaddr, *ifa;
    std::string     ip;

    if (getifaddrs(&ifaddr) == -1) {
        return "Error getting interface addresses";
    }

    for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
        if (ifa->ifa_addr == nullptr) {
            continue;
        }

        // 检查是否是 IPv4 地址
        if (ifa->ifa_addr->sa_family == AF_INET) {
            // 检查是否是 en0 网卡
            if (std::string(ifa->ifa_name) == "en0") {
                struct sockaddr_in* addr = (struct sockaddr_in*)ifa->ifa_addr;
                char                ipStr[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &addr->sin_addr, ipStr, sizeof(ipStr));
                ip = ipStr;
                break;
            }
        }
    }

    freeifaddrs(ifaddr);
    return ip.empty() ? "No IP found on en0" : ip;
}

template <typename K, typename V>
K findKeyByValue(const std::map<K, V>& map, const V& value) {
    // 遍历整个map，找到对应的key
    for (const auto& pair : map) {
        if (pair.second == value) {
            return pair.first;  // 返回找到的key
        }
    }
    throw std::runtime_error("Value not found in the map.");
}

static inline uint32_t read_u32(std::span<const char> bytes) {
    if (bytes.size() < sizeof(int32_t)) {
        throw std::out_of_range("Insufficient data for reading int32_t");
    }

    int32_t value;
    std::memcpy(&value, bytes.data(), sizeof(value));  // Copy the data into the value

    return ntohl(value);
}

// 写入 uint32_t 到 4 字节
static inline void write_u32(uint32_t value, std::span<char> bytes) {
    if (bytes.size() < 4) {
        throw std::out_of_range("Not enough space to write uint32_t");
    }
    bytes[0] = static_cast<char>((value >> 24) & 0xFF);
    bytes[1] = static_cast<char>((value >> 16) & 0xFF);
    bytes[2] = static_cast<char>((value >> 8) & 0xFF);
    bytes[3] = static_cast<char>(value & 0xFF);
}

// 校验和计算（简单示例，可以替换为更复杂的校验算法）
static inline int32_t compute_checksum(const std::string& data) {
    int32_t sum = 0;
    for (char c : data) {
        sum += static_cast<unsigned char>(c);
    }
    return sum;
}

class RpcError {
public:
    enum ErrorCode {
        InsufficientData = 9000,
        ConnectFailed,
        ReadEOF,
        ReadFailed,
        WriteFailed,
        ReadFrameFailed,
        WriteFrameFailed,
        UnregisteredMethod,
        InvalidFormat,
    };

public:
    explicit RpcError(int err_code) : err_code_{err_code} {}

public:
    [[nodiscard]]
    auto value() const noexcept -> int {
        return err_code_;
    }

    [[nodiscard]]
    auto message() const noexcept -> std::string_view {
        switch (err_code_) {
            case InsufficientData:
                return "Insufficient data";
            case ConnectFailed:
                return "Connect failed";
            case ReadEOF:
                return "Read eof";
            case ReadFailed:
                return "Read failed";
            case WriteFailed:
                return "Write failed";
            case ReadFrameFailed:
                return "Read frame failed";
            case WriteFrameFailed:
                return "Write frame failed";
            case UnregisteredMethod:
                return "Unregistered method";
            default:
                return strerror(err_code_);
        }
    }

private:
    int err_code_;
};

[[nodiscard]]
static inline auto make_rpc_error(int err) -> RpcError {
    assert(err >= 9000);
    return RpcError{err};
}

template <typename T>
using RpcResult = std::expected<T, RpcError>;

}  // namespace fastrpc::rpc::util
